﻿using Haidou.Wpf.UI.Util;
using Haidou.Wpf.UI.Windows;
using Haidou.Wpf.UI.Windows.Composer;
using Haidou.Wpf.UI.Windows.Other;
using Haidou.Wpf.Util;
using Haidou.Wpf.Util.Converters;
using Haidou.Wpf.Util.Settings;
using HandyControl.Controls;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;
using Application = System.Windows.Application;
using Window = System.Windows.Window;

namespace Haidou.Wpf.UI.ViewModel
{
	public class ApplicationViewModel : ApplicationBaseViewModel
	{
		#region Commands
		private static object _locker = new();
		public IExtendedCommand<int, bool> Open => new AdvancedRelayCommand<int, bool>
		{
			ExecuteAction = (startup, fromDebug) =>
			{

				//if (!fromDebug && UserSettings.All.StartMinimized)
				//	startup = -1;

				//如果文件是通过参数发送的，强制编辑器打开。
				if (!fromDebug && Arguments.FileNames.Any())
				{
					startup = 4;
				}

				switch (startup)
				{
					case -1: //Minimized.
						{
							return;
						}

					case 2: //Webcam recorder.
						{


							return;
						}

					case 3: //Board recorder.
						{

							return;
						}

					case 4: //Editor.
						{
							return;
						}

					case 5: //Options.
						{
							OpenOptions.Execute(null);
							return;
						}


					default: //Startup.
						{
							OpenStartup.Execute(null);
							return;
						}
				}
			}
		};

		public ICommand OpenStartup => new RelayCommand
		{
			ExecuteAction = a =>
			{
				Startup? startup = System.Windows.Application.Current.Windows.OfType<Startup>().FirstOrDefault();

				if (startup == null)
				{

					startup = new Startup();
					startup.Closed += (sender, args) => { CloseOrNot(); };

					startup.Show();
				}
				else
				{
					if (startup.WindowState == WindowState.Minimized)
					{
						startup.WindowState = WindowState.Normal;
					}

					startup.Activate();
				}
			}
		};





		public ICommand OpenLauncher => new RelayCommand
		{
			ExecuteAction = a =>
			{

			}
		};


		public ICommand OpenOptions => new RelayCommand
		{
			CanExecutePredicate = a => true, //TODO:总是让此窗口打开或检查是否有任何其他记录器处于活动状态？
			ExecuteAction = a =>
			{
				Options? options = Application.Current.Windows.OfType<Options>().FirstOrDefault();

				if (options == null)
				{
					options = new Options();
					options.Closed += (sender, args) =>
					{
						CloseOrNot();
					};

					//TODO:是否作为对话框打开？屏蔽其他窗口？
					options.Show();
				}
				else
				{
					if (options.WindowState == WindowState.Minimized)
					{
						options.WindowState = WindowState.Normal;
					}

					options.Activate();
				}
			}
		};



		public ICommand OpenShowMainWindowDisplay => new RelayCommand
		{
			CanExecutePredicate = a => true, //TODO:总是让此窗口打开或检查是否有任何其他记录器处于活动状态？
			ExecuteAction = a =>
			{
				MainWindow? options = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
				int tab = a as int? ?? 0; //选择要显示哪个选项卡的参数。

				if (options == null)
				{
					options = new MainWindow();
					options.Closed += (sender, args) =>
					{
						CloseOrNot();
					};

					//TODO:是否作为对话框打开？屏蔽其他窗口？
					options.Show();
				}
				else
				{
					if (options.WindowState == WindowState.Minimized)
					{
						options.WindowState = WindowState.Normal;
					}

					//options.Activate();//尝试将窗口置于前台并激活它。
					options.Show();

				}
			}
		};


		public ICommand OpenShowMain => new RelayCommand
		{
			CanExecutePredicate = a => true, //TODO:总是让此窗口打开或检查是否有任何其他记录器处于活动状态？
			ExecuteAction = a =>
			{
				MainWindow? options = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
				int tab = a as int? ?? 0; //选择要显示哪个选项卡的参数。

				if (options == null)
				{
					options = new MainWindow();
					options.Closed += (sender, args) =>
					{
						CloseOrNot();
					};

					//TODO:是否作为对话框打开？屏蔽其他窗口？
					options.Show();
				}
				else
				{
					if (options.WindowState == WindowState.Minimized)
					{
						options.WindowState = WindowState.Normal;
					}

					options.Activate();//尝试将窗口置于前台并激活它。
				}
			}
		};



		public ICommand OpenTo_DoPlanAssistant => new RelayCommand
		{
			CanExecutePredicate = a => true, //TODO:总是让此窗口打开或检查是否有任何其他记录器处于活动状态？
			ExecuteAction = a =>
			{
				To_DoPlanAssistant? options = Application.Current.Windows.OfType<To_DoPlanAssistant>().FirstOrDefault();
				int tab = a as int? ?? 0; //选择要显示哪个选项卡的参数。

				if (options == null)
				{
					options = new To_DoPlanAssistant();
					options.Closed += (sender, args) =>
					{
						CloseOrNot();
					};

					//TODO:是否作为对话框打开？屏蔽其他窗口？
					options.Show();
				}
				else
				{
					if (options.WindowState == WindowState.Minimized)
					{
						options.WindowState = WindowState.Normal;
					}

					options.Activate();//尝试将窗口置于前台并激活它。
				}
			}
		};

		public ICommand OpenTodoCalendarWindowt => new RelayCommand
		{
			CanExecutePredicate = a => true, //TODO:总是让此窗口打开或检查是否有任何其他记录器处于活动状态？
			ExecuteAction = a =>
			{
				TodoCalendarWindow? options = Application.Current.Windows.OfType<TodoCalendarWindow>().FirstOrDefault();
				int tab = a as int? ?? 0; //选择要显示哪个选项卡的参数。

				if (options == null)
				{
					options = new TodoCalendarWindow();
					options.Closed += (sender, args) =>
					{
						CloseOrNot();
					};

					//TODO:是否作为对话框打开？屏蔽其他窗口？
					options.Show();
				}
				else
				{
					if (options.WindowState == WindowState.Minimized)
					{
						options.WindowState = WindowState.Normal;
					}

					options.Activate();//尝试将窗口置于前台并激活它。
				}
			}
		};
		


		public ICommand OpenTodoCalendar => new RelayCommand
		{
			CanExecutePredicate = a => true,
			ExecuteAction = a =>
			{
				var win = Application.Current.Windows.OfType<Haidou.Wpf.UI.Windows.Composer.TodoCalendarWindow>().FirstOrDefault();
				if (win == null)
				{
					win = new Haidou.Wpf.UI.Windows.Composer.TodoCalendarWindow();
					win.Closed += (s,e)=> { CloseOrNot(); };
					win.Show();
				}
				else
				{
					if (win.WindowState == WindowState.Minimized) win.WindowState = WindowState.Normal;
					win.Activate();
				}
			}
		};




		public ICommand OpenMainWindowClose => new RelayCommand
		{
			CanExecutePredicate = a => true, //TODO:总是让此窗口打开或检查是否有任何其他记录器处于活动状态？
			ExecuteAction = a =>
			{
				MainWindow? options = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
				int tab = a as int? ?? 0; //选择要显示哪个选项卡的参数。
				if (options == null)
				{
					return;
				}
				if (options.WindowState == WindowState.Minimized)
				{
					options.WindowState = WindowState.Normal;
				}

				options.Close();//尝试将窗口置于前台并激活它。
			}
		};




		#endregion

		#region Methods


		private void CloseOrNot()
		{
			//关闭时，检查是否是最后一个窗口，如果是配置的行为，则关闭。
			if (UserSettings.All.ShowNotificationIcon && UserSettings.All.KeepOpen)
			{
				return;
			}

			//我们只需要检查包含内容的已加载窗口，因为任何特殊窗口都可能是打开的。
			if (Application.Current.Windows.Cast<System.Windows.Window>().Count(window => window.HasContent) == 0)
			{
				//关闭时安装可用的更新。
				if (UserSettings.All.InstallUpdates)
				{
					InstallUpdate();
				}

				if (UserSettings.All.DeleteCacheWhenClosing)
				{
					StorageUtils.PurgeCache();
				}

				Application.Current.Shutdown(2);
			}
		}

		private void Interact(int action, int open)
		{
			switch (action)
			{
				case 1: //打开窗口
					{
						switch (open)
						{
							case 1: //Startup.
								{
									OpenLauncher.Execute(null);
									break;
								}

							case 3: //Webcam.
								{

									break;
								}
							case 4: //Board.
								{

									break;
								}
							case 5: //Editor.
								{

									break;
								}
						}

						break;
					}

				case 2: //最小化/恢复所有窗口。
					{
						List<Window> all = Application.Current.Windows.OfType<Window>().Where(w => w.Content != null).ToList();

						if (all.Count == 0)
						{
							Interact(1, open);
							return;
						}

						if (all.Any(n => n.WindowState != WindowState.Minimized))
						{
							//最小化所有窗口，禁用之前，以防止一些行为。
							foreach (Window? f in all)
							{
								f.IsEnabled = false;
							}

							foreach (Window? f in all)
							{
								f.WindowState = WindowState.Minimized;
							}

							foreach (Window? f in all)
							{
								f.IsEnabled = true;
							}
						}
						else
						{
							//Restore all windows.
							foreach (Window? window in all)
							{
								window.WindowState = WindowState.Normal;
							}
						}

						break;
					}

				case 3: //Minimize all windows.
					{
						List<Window> all = Application.Current.Windows.OfType<Window>().Where(w => w.Content != null).ToList();

						if (all.Count == 0)
						{
							Interact(1, open);
							return;
						}

						foreach (Window? window in all)
						{
							window.WindowState = WindowState.Minimized;
						}

						break;
					}

				case 4: //Restore all windows.
					{
						List<Window> all = Application.Current.Windows.OfType<Window>().Where(w => w.Content != null).ToList();

						if (all.Count == 0)
						{
							Interact(1, open);
							return;
						}

						foreach (Window? window in all)
						{
							window.WindowState = WindowState.Normal;
						}

						break;
					}
			}
		}

		/// <summary>
		/// 清除临时文件
		/// </summary>
		internal void ClearTemporaryFiles()
		{
			try
			{
				if (!UserSettings.All.AutomaticCleanUp || Global.IsCurrentlyDeletingFiles || string.IsNullOrWhiteSpace(UserSettings.All.TemporaryFolderResolved))
				{
					return;
				}

				Global.IsCurrentlyDeletingFiles = true;

				ClearRecordingCache();
				ClearUpdateCache();
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "Automatic clean up");
			}
			finally
			{
				Global.IsCurrentlyDeletingFiles = false;
				CheckDiskSpace();
			}
		}

		private void ClearRecordingCache()
		{
			try
			{
				string path = Path.Combine(UserSettings.All.TemporaryFolderResolved, "海豆Desktop", "Recording");

				if (!Directory.Exists(path))
				{
					return;
				}

				List<DirectoryInfo> list = Directory.GetDirectories(path).Select(x => new DirectoryInfo(x))
					.Where(w => (DateTime.Now - w.CreationTime).TotalDays > (UserSettings.All.AutomaticCleanUpDays > 0 ? UserSettings.All.AutomaticCleanUpDays : 5)).ToList();

				//var list = Directory.GetDirectories(path).Select(x => new DirectoryInfo(x));


			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "Automatic clean up - Recordings");
			}
		}

		private void ClearUpdateCache()
		{
			try
			{
				string path = Path.Combine(UserSettings.All.TemporaryFolderResolved, "海豆Desktop", "Updates");

				if (!Directory.Exists(path))
				{
					return;
				}

				List<FileInfo> list = Directory.EnumerateFiles(path).Select(x => new FileInfo(x))
					.Where(w => (DateTime.Now - w.CreationTime).TotalDays > (UserSettings.All.AutomaticCleanUpDays > 0 ? UserSettings.All.AutomaticCleanUpDays : 5)).ToList();

				foreach (FileInfo? file in list)
				{
					File.Delete(file.FullName);
				}
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "Automatic clean up - Updates");
			}
		}

		internal void CheckDiskSpace()
		{
			if (string.IsNullOrWhiteSpace(UserSettings.All.TemporaryFolderResolved))
			{
				return;
			}

			try
			{
				bool isRelative = !string.IsNullOrWhiteSpace(UserSettings.All.TemporaryFolderResolved) && !Path.IsPathRooted(UserSettings.All.TemporaryFolderResolved);
				DriveInfo drive = new((isRelative ? Path.GetFullPath(UserSettings.All.TemporaryFolderResolved) : UserSettings.All.TemporaryFolderResolved).Substring(0, 1));

				Global.AvailableDiskSpacePercentage = drive.AvailableFreeSpace * 100d / drive.TotalSize; //获取剩余空间的百分比。
				Global.AvailableDiskSpace = drive.AvailableFreeSpace;

				//如果剩下不到2GB。
				if (drive.AvailableFreeSpace < 2_000_000_000)
				{
					//Application.Current.Dispatcher?.Invoke(() => NotificationManager.AddNotification(LocalizationHelper.GetWithFormat("S.Editor.Warning.LowSpace", Math.Round(Global.AvailableDiskSpacePercentage, 2)),
					//	StatusType.Warning, "disk", () => App.MainViewModel.OpenOptions.Execute(Options.TempFilesIndex)));
				}
				else
				{
					Application.Current.Dispatcher?.Invoke(() => NotificationManager.RemoveNotification(r => r.Tag == "disk"));
				}
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "Error while checking the space left in disk");
			}
		}

		/// <summary>
		/// 发送反馈   暂时没有API服务 后续开发DTO
		/// </summary>
		internal void SendFeedback()
		{
			try
			{
				return;
				if (string.IsNullOrWhiteSpace(UserSettings.All.TemporaryFolderResolved))
				{
					return;
				}

				string path = Path.Combine(UserSettings.All.TemporaryFolderResolved, "海豆Desktop", "Feedback");

				if (!Directory.Exists(path))
				{
					return;
				}

				IEnumerable<FileInfo> list = new DirectoryInfo(path).EnumerateFiles("*.html", SearchOption.TopDirectoryOnly);

				foreach (FileInfo file in list)
				{
					//Get zip with same name as file  获取与文件同名的zip文件
					string zip = Path.Combine(file.DirectoryName, file.Name.Replace(".html", ".zip"));

					List<string> fileList = null;

					if (File.Exists(zip))
					{
						fileList = new List<string> { zip };
					}

					//if (!FeedbackHelper.Send(File.ReadAllText(file.FullName), fileList))
					//    continue;

					File.Delete(file.FullName);

					if (File.Exists(zip))
					{
						File.Delete(zip);
					}
				}
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "Automatic feedback||自动反馈");
			}
		}

		public async Task CheckForUpdates(bool forceCheck = false)
		{

			Global.UpdateAvailable = null;


			if (!forceCheck && !UserSettings.All.CheckForUpdates)
			{
				return;
			}



			//如果该应用程序是由Chocolatey安装的，请避免通过正常方式进行更新。 Chocolatey 包管理  安装应用
			if (await IsChocolateyPackage())
			{
				return;
			}

			//尝试先在检查更新，然后回到
			await CheckOnqx5ai();


		}

		/// <summary>
		/// Chocolatey  包装
		/// </summary>
		/// <returns></returns>
		private async Task<bool> IsChocolateyPackage()
		{
			try
			{
				return true;
			}
			catch (Exception e)
			{
				LogWriter.Log(e, "Not possible to detect Chocolatey package.||无法检测Chocolate安装包");
				return false;
			}
		}


		/// <summary>
		/// 检测是否需要更新 服务器
		/// </summary>
		/// <returns></returns>
		public static async Task<bool> CheckOnqx5ai()
		{
			try
			{


				//暂无代理转发
				//System.Net.IWebProxy? proxy = WebHelper.GetProxy();
				//HttpClientHandler handler = new HttpClientHandler
				//{
				//	Proxy = proxy,
				//	UseProxy = proxy != null
				//};

				//using HttpClient client = new HttpClient(handler);
				using HttpClient client = new();
				client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393");
				string URL = "";
				//if (AutoUpdate.IsVersion.Contains("海豆Desktop"))
				//{

				//	URL = Arguments.Is64BitProcess ? "https://app.5ai.top/app/version_hub_x64";

				//}


				using HttpResponseMessage response = await client.GetAsync(URL);
				string result = await response.Content.ReadAsStringAsync();

				JObject jsonReader = JSON.Parse<JObject>(result);

				string Versio = jsonReader["version"].ToString();
				string Downloadaddress = jsonReader["download_url"].ToString();
				string title = jsonReader["title"].ToString();
				string type = jsonReader["type"].ToString();


				if (jsonReader["ForceDownloadOfTheInstallationPackageVersion"] != null)
				{
					string ForceDownloadOfTheInstallationPackageVersion = jsonReader["ForceDownloadOfTheInstallationPackageVersion"].ToString();

					if (!string.IsNullOrEmpty(ForceDownloadOfTheInstallationPackageVersion))
					{
						bool forc = ForceDownloadOfTheInstallationPackageVersion.ToBoolean();
						UserSettings.All.ForceDownloadOfTheInstallationPackageVersion = forc;
						UserSettings.Save();
					}
				}

				JObject release = jsonReader;

				Version version = Version.Parse(Versio ?? "0.1");
				Version? AssemblyVersion = Assembly.GetExecutingAssembly().GetName().Version;

				//服务器获取的版本小于 =当前版本无需更新
				if (version.Major == 0 || version <= AssemblyVersion)
				{
					UpdateAvailable.IsUpdate = false;
					return true;
				}
				else
				{

					UpdateAvailable.IsUpdate = true;
				}



				ParseDownloadUrls(release, version);

				//Application.Current.Dispatcher?.Invoke(() => NotificationManager.AddNotification(string.Format(LocalizationHelper.Get("S.Updater.NewRelease.Info"),
				//	Global.UpdateAvailable.Version), StatusType.Update, "update", PromptUpdate));



				//下载应用程序关闭时要安装的更新。
				if (UserSettings.All.InstallUpdates && Global.UpdateAvailable.HasDownloadLink)
				{
					await DownloadUpdate();
				}

				return true;
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "无法在服务器上检查更新");
				return false;
			}
			finally
			{
				GC.Collect();
			}
		}

		/// <summary>
		/// 解析下载URL
		/// </summary>
		/// <param name="release"></param>
		/// <param name="version"></param>
		/// <param name="fromQx5ai"></param>
		/// <returns></returns>
		private static bool ParseDownloadUrls(JObject release, Version version, bool fromQx5ai = true)
		{
			///获取运行当前应用程序的平台体系结构。
			string moniker = RuntimeInformation.OSArchitecture switch
			{
				Architecture.X64 => "x64",
				Architecture.X86 => "x86",
				_ => "arm64"
			};


			{
				//获得便携或安装包，轻或轻。
				//.2.36.Portable.x64.zip
				//.2.36.Portable.zip
				//Or
				//.2.36.Setup.x64.msi
				//.2.36.Setup.msi

				string installer = release["download_url"].ToString();

				//如果缺少light(框架相关)变体，请下载完整的软件包。

				return SetDownloadDetails(fromQx5ai, version, release, installer);


			}

		}

		/// <summary>
		/// 设置下载详细信息
		/// </summary>
		/// <param name="fromQx5ai">来自Github</param>
		/// <param name="version">版本</param>
		/// <param name="release">xml</param>
		/// <param name="installer">安装程序</param>
		/// <param name="portable">轻便的</param>
		/// <returns></returns>
		private static bool SetDownloadDetails(bool fromQx5ai, Version version, JObject release, string installer, XElement portable = null)
		{


			if (installer == null)
			{
				Global.UpdateAvailable = new UpdateAvailable
				{
					IsFromQx5ai = fromQx5ai,
					Version = version,
					//Description = AutoUpdate.DescriptionText,
					MustDownloadManually = true
				};

				return false;
			}

			if (fromQx5ai)
			{
				Global.UpdateAvailable = new UpdateAvailable
				{
					Version = version,
					//Description = AutoUpdate.DescriptionText,//有什么新消息  更新内容等，暂时本地直接填，不从服务器获取

					PortableDownloadUrl = "",//
					PortableSize = 0,
					PortableName = "QxznAI-Hub-Install.exe",
					//	var Versio = jsonReader["version"].ToString();

					//var Downloadaddress = jsonReader["download_url"].ToString();
					//var title = jsonReader["title"].ToString();
					//var type = jsonReader["type"].ToString();  

					InstallerDownloadUrl = release["download_url"].ToString() ?? "",
					InstallerSize = Convert.ToUInt32(release["size"].ToString()),

					InstallerName = "QxznAI-Hub-Install.exe"
				};

				return true;
			}

			Global.UpdateAvailable = new UpdateAvailable
			{
				IsFromQx5ai = false,
				Version = version,
				PortableDownloadUrl = portable?.Element("link")?.Value ?? "",
				InstallerDownloadUrl = release["link"].ToString() ?? "",
			};

			return true;
		}



		internal static async Task<bool> DownloadUpdate()
		{
			try
			{
				lock (UserSettings.Lock)
				{
					if (string.IsNullOrWhiteSpace(UserSettings.All.TemporaryFolderResolved) || Global.UpdateAvailable.IsDownloading)
					{
						return false;
					}

					string folder = Path.Combine(UserSettings.All.TemporaryFolderResolved, "海豆Desktop", "Updates");

					if (!Directory.Exists(folder))
					{
						Directory.CreateDirectory(folder);
					}

					Global.UpdateAvailable.ActivePath = Path.Combine(folder, Global.UpdateAvailable.ActiveName);

					//检查安装程序是否已经下载。
					if (File.Exists(Global.UpdateAvailable.ActivePath))
					{
						//小问题，如果出于某种原因，更新具有完全相同的大小，这将无法正常工作。我需要查一下哈希。
						if (GetSize(Global.UpdateAvailable.ActivePath) == Global.UpdateAvailable.ActiveSize)
						{
							return false;
						}

						File.Delete(Global.UpdateAvailable.ActivePath);
					}

					Global.UpdateAvailable.IsDownloading = true;
				}

				System.Net.IWebProxy? proxy = WebHelper.GetProxy();
				HttpClientHandler handler = new()
				{
					Proxy = proxy,
					UseProxy = proxy != null,
				};

				//TODO: Use HttpClientFactory
				//https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
				//https://marcominerva.wordpress.com/2019/03/13/using-httpclientfactory-with-wpf-on-net-core-3-0/

				using (HttpClient client = new(handler))
				{
					client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393");

					HttpResponseMessage response = await client.GetAsync(Global.UpdateAvailable.ActiveDownloadUrl);

					if (response.IsSuccessStatusCode)
					{
						Stream stream = await response.Content.ReadAsStreamAsync();
						FileInfo fileInfo = new(Global.UpdateAvailable.ActivePath);
						await using FileStream fileStream = fileInfo.OpenWrite();
						await stream.CopyToAsync(fileStream);
					}
					else
					{
						LogWriter.Log("Impossible to download update.无法下载更新");

						throw new FileNotFoundException("Impossible to download update.无法下载更新");
					}
				}

				Global.UpdateAvailable.MustDownloadManually = false;
				Global.UpdateAvailable.TaskCompletionSource?.TrySetResult(true);
				return true;
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "Impossible to automatically download update.无法自动下载更新");
				Global.UpdateAvailable.MustDownloadManually = true;
				Global.UpdateAvailable.TaskCompletionSource?.TrySetResult(false);
				return false;
			}
			finally
			{
				Global.UpdateAvailable.IsDownloading = false;
			}
		}


		/// <summary>
		/// 开始安装 。注意弹出新窗口后，选择确定返回到这里继续安装操作
		/// </summary>
		/// <param name="wasPromptedManually"></param>
		/// <returns></returns>
		internal static bool InstallUpdate(bool wasPromptedManually = false)
		{
			try
			{
				//没有新版本可用。
				if (Global.UpdateAvailable == null)
				{
					return false;
				}

				//TODO:检查Windows是否没有关闭。

				bool runAfterwards = false;

				//提示条件:
				//未配置为自动下载更新，或者
				//配置为下载，但设置为提示，或者
				//更新二进制检测失败(需要手动更新)或
				//下载未完成(可能是因为Fosshub上的查询触发了通知)。
				if (UserSettings.All.PromptToInstall || !UserSettings.All.InstallUpdates || string.IsNullOrWhiteSpace(Global.UpdateAvailable.ActivePath)
					|| Global.UpdateAvailable.MustDownloadManually)
				{
					//DownloadDialog download = new() { WasPromptedManually = wasPromptedManually };
					//bool? result = download.ShowDialog();
					//注意弹出新窗口后，选择确定返回到这里继续安装操作
					//if (!result.HasValue || !result.Value)
					//{
					//	return false;
					//}

					//runAfterwards = download.RunAfterwards;
				}

				//只有下载了更新，才尝试安装。
				if (!File.Exists(Global.UpdateAvailable.ActivePath))
				{
					return false;
				}

				//if (UserSettings.All.PortableUpdate || IdentityHelper.ApplicationType == ApplicationTypes.FullMultiMsix)
				//{
				//	//在便携或Msix模式下，只需打开zip/msix文件并关闭app。
				//	ProcessHelper.StartWithShell(Global.UpdateAvailable.ActivePath);
				//	return true;
				//}

				//检测已安装的组件。
				List<string> files = Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory).ToList();
				bool isInstaller = files.Any(x => x.ToLowerInvariant().EndsWith("Haidou.Wpf.UI.visualelementsmanifest.xml"));
				bool hasGifski = files.Any(x => x.ToLowerInvariant().EndsWith("gifski.dll"));
				bool hasDesktopShortcut = File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), ".lnk")) ||
										 File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory), ".lnk"));
				bool hasMenuShortcut = File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft", "Windows", "Start Menu", "Programs", ".lnk")) ||
									  File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Microsoft", "Windows", "Start Menu", "Programs", ".lnk"));

				string exe = Path.Combine(Global.UpdateAvailable.ActivePath);
				if (File.Exists(exe))
				{
					ProcessStartInfo p = new()
					{
						FileName = exe
					};
					using (Process process = new()
					{ StartInfo = p })
					{
						process.Start();
					}
				}


				return true;
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "Impossible to automatically install update||无法自动安装更新");

				//ErrorDialog.Ok("Haidou.Wpf.UI", "It was not possible to install the update||无法安装更新", ex.Message, ex);
				return false;
			}
		}

		private static long GetSize(string path)
		{
			FileInfo info = new(path);
			info.Refresh();

			return info.Length;
		}

		#endregion
	}

	public interface IExtendedCommand<in T, in TR>
	{
		event EventHandler CanExecuteChanged;

		bool CanExecute(object parameter);

		void Execute(T parameter, TR secondParameter = default);
	}

	public class RelayCommand : ICommand
	{
		public Predicate<object> CanExecutePredicate { get; set; }
		public Action<object> ExecuteAction { get; set; }

		public RelayCommand(Predicate<object> canExecute, Action<object> execute)
		{
			CanExecutePredicate = canExecute;
			ExecuteAction = execute;
		}

		public RelayCommand()
		{ }

		public event EventHandler CanExecuteChanged
		{
			add => CommandManager.RequerySuggested += value;
			remove => CommandManager.RequerySuggested -= value;
		}

		public bool? CanExecute(object parameter)
		{
			return CanExecutePredicate == null || CanExecutePredicate(parameter);
		}

		public void Execute(object parameter)
		{
			ExecuteAction(parameter);
		}

		bool ICommand.CanExecute(object? parameter)
		{
			//throw new NotImplementedException();
			return true;
		}
	}

	public class AdvancedRelayCommand<T, TR> : IExtendedCommand<T, TR>
	{
		public Predicate<object> CanExecutePredicate { get; set; }
		public Action<T, TR> ExecuteAction { get; set; }

		public AdvancedRelayCommand(Predicate<object> canExecute, Action<T, TR> execute)
		{
			CanExecutePredicate = canExecute;
			ExecuteAction = execute;
		}

		public AdvancedRelayCommand()
		{ }

		public event EventHandler CanExecuteChanged
		{
			add => CommandManager.RequerySuggested += value;
			remove => CommandManager.RequerySuggested -= value;
		}

		public bool CanExecute(object parameter)
		{
			return CanExecutePredicate == null || CanExecutePredicate(parameter);
		}

		public void Execute(T parameter, TR secondParamater = default)
		{
			ExecuteAction(parameter, secondParamater);
		}
	}

	public class ObsoleteAdvancedRelayCommand : RoutedUICommand, ICommand
	{
		public Predicate<object> CanExecutePredicate { get; set; }
		public Action<object> ExecuteAction { get; set; }

		public ObsoleteAdvancedRelayCommand()
		{ }

		public ObsoleteAdvancedRelayCommand(string text, string name, Type ownerType, InputGestureCollection inputGestures) : base(text, name, ownerType, inputGestures)
		{ }

		bool ICommand.CanExecute(object parameter)
		{
			return CanExecutePredicate == null || CanExecutePredicate(parameter);
		}

		void ICommand.Execute(object parameter)
		{
			ExecuteAction(parameter);
		}

		//public bool CanExecute(object parameter)
		//{
		//    return CanExecutePredicate == null || CanExecutePredicate(parameter);
		//}

		//public void Execute(object parameter)
		//{
		//    ExecuteAction(parameter);
		//}
	}
}
